#region File Description
//-----------------------------------------------------------------------------
// OptionsMenuScreen.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using InversPong.Model;
using InversPong.Services;
#endregion

namespace InversPong
{
    /// <summary>
    /// The options screen is brought up over the top of the main menu
    /// screen, and gives the user a chance to configure the game
    /// in various hopefully useful ways.
    /// </summary>
    class OptionsMenuScreen : MenuScreen
    {
        #region Fields

        

        
        MenuEntry commands1;
        MenuEntry commands2;
        MenuEntry musicVolume;
        MenuEntry soundVolume;
        MenuEntry sensibility1;
        MenuEntry sensibility2;
        MenuEntry initialLifesCount;
        MenuEntry fullScreen;

        
        
        static Keys upKey1 = Keys.Z;
        static Keys downKey1 = Keys.S;
        static Keys upKey2 = Keys.O;
        static Keys downKey2 = Keys.L;
        static int currentMusicVolume = 40;
        static int currentVolume = 70;
        static decimal currentSensibility1 = 1;
        static decimal currentSensibility2 = 1;
        static decimal counter1 = 4;
        static decimal counter2 = 4;
        static int currentLifeCount = Player.defaultPlayerLives;
        static string[] themes = {"Default"};
        static bool isFullScreen = false;

        #endregion

        #region Initialization


        /// <summary>
        /// Constructor.
        /// </summary>
        public OptionsMenuScreen()
            : base("Options")
        {
            
            // Create our menu entries.
            
            commands1 = new MenuEntry(string.Empty);
            commands2 = new MenuEntry(string.Empty);
            musicVolume = new MenuEntry(string.Empty);
            sensibility1 = new MenuEntry(string.Empty);
            sensibility2 = new MenuEntry(string.Empty);
            initialLifesCount = new MenuEntry(string.Empty);
            fullScreen = new MenuEntry(string.Empty);

            SetMenuEntryText();

            MenuEntry back = new MenuEntry("Back");

            // Hook up menu event handlers.
           
            commands1.Selected += CommandsSelected;
            commands2.Selected += CommandsSelected;
            musicVolume.Selected += MusicVolumeSelected; musicVolume.Decrease += MusicDecreased;
            sensibility1.Selected += SensibilitySelected; sensibility1.Decrease += sensibilityDecreased;
            sensibility2.Selected += SensibilitySelected; sensibility2.Decrease += sensibilityDecreased;
            initialLifesCount.Selected += LifeCountSelected; initialLifesCount.Decrease += lifeCountDecreased;
            fullScreen.Selected += SizeableWindow; fullScreen.Decrease += SizeableWindow;
            back.Selected += OnCancel;
            
            // Add entries to the menu.
            
            MenuEntries.Add(commands1);
            MenuEntries.Add(commands2);
            MenuEntries.Add(musicVolume);
            MenuEntries.Add(sensibility1);
            MenuEntries.Add(sensibility2);
            MenuEntries.Add(initialLifesCount);
            MenuEntries.Add(fullScreen);
            MenuEntries.Add(back);
        }


        /// <summary>
        /// Fills in the latest values for the options screen menu text.
        /// </summary>
        void SetMenuEntryText()
        {
            commands1.Text = "Commands for player Blue : " + upKey1  + "  |  " + downKey1 ;

            commands2.Text = "Commands for player Red : " + upKey2 + "  |  " + downKey2;

            musicVolume.Text = "Music volume : " + currentMusicVolume; 

            sensibility1.Text = "Sensibility for player Blue : " + currentSensibility1;

            sensibility2.Text = "Sensibility for player Red: " + currentSensibility2;
            
            initialLifesCount.Text = "Initial number of lives : " + currentLifeCount;
            
            fullScreen.Text = "Full screen : " + isFullScreen;
        }


        #endregion

        #region Handle Input


        /// <summary>
        /// Responds to user input, changing the selected entry and accepting
        /// or cancelling the menu.
        /// </summary>
        public override void HandleInput(InputState input)
        {
            PlayerIndex playerIndex;
            // Increases the value of the menu entry
            if (input.IsMenuRight(ControllingPlayer, out playerIndex))
            {
                IncreaseEntryValue(selectedEntry, playerIndex);
            }

            // Decreases the value of the menu entry
            if (input.IsMenuLeft(ControllingPlayer, out playerIndex))
            {
                DecreaseEntryValue(selectedEntry, playerIndex);
            }
            
            base.HandleInput(input);
        }

        

        private void IncreaseEntryValue(int selectedEntry, PlayerIndex playerIndex)
        {
            MenuEntries[selectedEntry].OnSelectEntry(playerIndex);   
        }

        private void DecreaseEntryValue(int selectedEntry, PlayerIndex playerIndex)
        {
            MenuEntries[selectedEntry].OnDecreaseEntry(playerIndex);
        }

        
        /// <summary>
        /// Event handler for when the Command menu entry is selected.
        /// </summary>
        void CommandsSelected(object sender, PlayerIndexEventArgs e)
        {
            string message = "Type the command you want to assign to go up and press Enter";

            OptionEntryBoxScreen commandMessageBox = new OptionEntryBoxScreen(message, false);
            
            ScreenManager.AddScreen(commandMessageBox, base.ControllingPlayer);

            commandMessageBox.KeyTyped += ConfirmUpCommand;

        }
        void ConfirmUpCommand(object sender, PlayerTypedKey e)
        {
            if (selectedEntry == 0)
            {
                upKey1 = e.Key;
            }
            else {
                upKey2 = e.Key;
            }

            string message = "Type the command you want to assign to : go down and press Enter \n" + "Reminder : " + e.Key + " to go up ";

            OptionEntryBoxScreen commandMessageBox = new OptionEntryBoxScreen(message, false);
            
            ScreenManager.AddScreen(commandMessageBox, base.ControllingPlayer);

            commandMessageBox.KeyTyped += ConfirmDownCommand;

            SetMenuEntryText();
        }
        void ConfirmDownCommand(object sender, PlayerTypedKey e)
        {

            if (selectedEntry == 0)
            {
                downKey1 = e.Key;
            }
            else
            {
                downKey2 = e.Key;
            }

            assignKeys();
            SetMenuEntryText();
        }

        

        void assignKeys() {
            if (upKey1 != downKey1 && upKey2 != downKey2 && upKey1 != upKey2 && upKey1 != downKey2)
            {
                
                    base.ScreenManager.GameModel.Player1.Up = upKey1;
                    base.ScreenManager.GameModel.Player1.Down = downKey1;

                    base.ScreenManager.GameModel.Player2.Up = upKey2;
                    base.ScreenManager.GameModel.Player2.Down = downKey2;
                
            }
            else {

                MessageBoxScreen errorBox = new MessageBoxScreen("The same key can't be assigned to several commands. \nPlease make sure to assign different keys\nto different commands of the game", false);

                ScreenManager.AddScreen(errorBox, base.ControllingPlayer);

                upKey1 = Keys.Z;
                downKey1 = Keys.S;
                upKey2 = Keys.O;
                downKey2 = Keys.L;

            }
            
        }

        /// <summary>
        /// Event handler for when the music volume menu entry is selected.
        /// </summary>
        void MusicVolumeSelected(object sender, PlayerIndexEventArgs e)
        {

            if (currentMusicVolume < 100)
                currentMusicVolume += 10;

            applyMusicVolume(currentMusicVolume);
            SetMenuEntryText();
            
        }
        void MusicDecreased(object sender, PlayerIndexEventArgs e)
        {

            if (currentMusicVolume > 0)
                currentMusicVolume -= 10;
            applyMusicVolume(currentMusicVolume);
            SetMenuEntryText();
        }
        void applyMusicVolume(int volume){
            
                SimpleMusicPlayer musicPlayer = (SimpleMusicPlayer)base.ScreenManager.Game.Services.GetService(typeof(IMusicPlayer));
                musicPlayer.Volume = volume / 100f;
                       
        }


        




        void SensibilitySelected(object sender, PlayerIndexEventArgs e)
        {
            if (selectedEntry == 3)
            {
                if (currentSensibility1 < 3)
                {
                    currentSensibility1 += (decimal)0.1;
                    counter1 += (decimal)0.4;
                }
            }
            else {
                if (currentSensibility2 < 3)
                {
                    currentSensibility2 += (decimal)0.1;
                    counter2 += (decimal)0.4;
                }
            }
            applySensibility(selectedEntry);
            SetMenuEntryText();
        }
        void sensibilityDecreased(object sender, PlayerIndexEventArgs e) {
            
            if (selectedEntry == 3)
            {
                if (currentSensibility1 > (decimal)0.1)
                {
                    currentSensibility1 -= (decimal)0.1;
                    if (counter1 > 0)
                    {
                        counter1 -= (decimal)0.4;
                    }
                }
                
            }
            else {
                if (currentSensibility2 > (decimal)0.1)
                {
                    currentSensibility2 -= (decimal)0.1;
                    if (counter2 > 0)
                    {
                        counter2 -= (decimal)0.4;
                    }
                }
            }

            applySensibility(selectedEntry);
            
            SetMenuEntryText();
        }
        void applySensibility(int index) {
            if (index == 3)
            {
                base.ScreenManager.GameModel.Player1.Bat.Speed = counter1;
            }
            else
            {
                base.ScreenManager.GameModel.Player2.Bat.Speed = counter2;
            }
        }


        
        void LifeCountSelected(object sender, PlayerIndexEventArgs e)
        {
            if (currentLifeCount < 4)
                currentLifeCount++;
            applyLifeCount(currentLifeCount);
            SetMenuEntryText();
        }

        void lifeCountDecreased(object sender, PlayerIndexEventArgs e)
        {
            if (currentLifeCount > 1)
                currentLifeCount--;
            applyLifeCount(currentLifeCount);
            SetMenuEntryText();
        }
        void applyLifeCount(int lifeCount) {
            base.ScreenManager.GameModel.Player1.InitialLives = lifeCount;
            base.ScreenManager.GameModel.Player2.InitialLives = lifeCount;
        }


        void SizeableWindow(object sender, PlayerIndexEventArgs e)
        {
            isFullScreen = !isFullScreen;

            SetMenuEntryText();
            GraphicsDeviceManager deviceManager = (GraphicsDeviceManager)base.ScreenManager.Game.Services.GetService(typeof(IGraphicsDeviceManager));
           
            deviceManager.ToggleFullScreen();           
        }

        #endregion


    }
}
